package com.sso.auth.service.impl;

import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.sso.auth.dto.LoginRequest;
import com.sso.auth.dto.LoginResponse;
import com.sso.auth.entity.User;
import com.sso.auth.convert.UserConverter;
import com.sso.auth.service.AuthService;
import com.sso.auth.service.UserService;
import com.sso.common.exception.BusinessException;
import io.jsonwebtoken.Claims;
import com.sso.auth.domain.TokenDomainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {
    
    private final UserService userService;
    private final UserConverter userConverter;
    private final StringRedisTemplate redisTemplate;
    private final TokenDomainService tokenDomainService;
    
    @Value("${jwt.secret:defaultSecretKey}")
    private String jwtSecret;
    
    @Value("${jwt.expiration:3600}")
    private Long jwtExpiration;
    
    @Value("${jwt.refresh-expiration:86400}")
    private Long jwtRefreshExpiration;
    
    @Override
    public LoginResponse login(LoginRequest request, String clientIp) {
        // 验证用户名密码
        User user = userService.findByUsername(request.getUsername());
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }
        
        if (user.getStatus() == 0) {
            throw new BusinessException("用户已被禁用");
        }
        
        if (!BCrypt.checkpw(request.getPassword(), user.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        
        // 生成令牌
        String accessToken = tokenDomainService.generateAccessToken(user, jwtExpiration);
        String refreshToken = tokenDomainService.generateRefreshToken(user, jwtRefreshExpiration);
        
        // 更新最后登录信息
        userService.updateLastLoginInfo(user.getId(), clientIp);
        
        // 存储令牌到Redis
        String tokenKey = "token:" + user.getId();
        redisTemplate.opsForValue().set(tokenKey, accessToken, jwtExpiration, TimeUnit.SECONDS);
        
        // 构建响应
        LoginResponse response = new LoginResponse();
        response.setAccessToken(accessToken);
        response.setRefreshToken(refreshToken);
        response.setExpiresIn(jwtExpiration);
        
        response.setUserInfo(userConverter.userToUserInfo(user));
        
        return response;
    }
    
    @Override
    public void logout(String token) {
        if (StrUtil.isBlank(token)) {
            return;
        }
        
        try {
            Claims claims = tokenDomainService.parseToken(token);
            
            Long userId = Long.valueOf(claims.getSubject());
            String tokenKey = "token:" + userId;
            redisTemplate.delete(tokenKey);
        } catch (Exception e) {
            log.warn("登出时解析令牌失败: {}", e.getMessage());
        }
    }
    
    @Override
    public LoginResponse refreshToken(String refreshToken) {
        if (StrUtil.isBlank(refreshToken)) {
            throw new BusinessException("刷新令牌不能为空");
        }
        
        try {
            Claims claims = tokenDomainService.parseToken(refreshToken);
            
            Long userId = Long.valueOf(claims.getSubject());
            User user = userService.findByUsername(claims.get("username", String.class));
            
            if (user == null || user.getStatus() == 0) {
                throw new BusinessException("用户不存在或已被禁用");
            }
            
            // 生成新的访问令牌
            String newAccessToken = tokenDomainService.generateAccessToken(user, jwtExpiration);
            
            // 更新Redis中的令牌
            String tokenKey = "token:" + userId;
            redisTemplate.opsForValue().set(tokenKey, newAccessToken, jwtExpiration, TimeUnit.SECONDS);
            
            LoginResponse response = new LoginResponse();
            response.setAccessToken(newAccessToken);
            response.setRefreshToken(refreshToken);
            response.setExpiresIn(jwtExpiration);
            
            return response;
        } catch (Exception e) {
            throw new BusinessException("刷新令牌无效");
        }
    }
    
    @Override
    public boolean validateToken(String token) {
        if (StrUtil.isBlank(token)) {
            return false;
        }
        
        try {
            Claims claims = tokenDomainService.parseToken(token);
            
            Long userId = Long.valueOf(claims.getSubject());
            String tokenKey = "token:" + userId;
            String storedToken = redisTemplate.opsForValue().get(tokenKey);
            
            return token.equals(storedToken);
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public LoginResponse.UserInfo getUserInfo(String token) {
        if (StrUtil.isBlank(token)) {
            return null;
        }
        
        try {
            Claims claims = tokenDomainService.parseToken(token);
            
            String username = claims.get("username", String.class);
            User user = userService.findByUsername(username);
            
            if (user == null || user.getStatus() == 0) {
                return null;
            }
            
            return userConverter.userToUserInfo(user);
        } catch (Exception e) {
            return null;
        }
    }
    
    
} 